#include "matchhandler.h"
#include "proto/message.pb.h"
#include "db/dbmanager.h"
#include "game/matchroom.h"
#include "utils/encodetool.h"
#include "log.h"

static Logger::ptr lvqiang = LoggerMgr::GetInstance()->GetLogger("lvqiang");

void MatchHandler::SetMatchModel(const void* data, int size)
{
    m_matchModel.ParseFromArray(data, size);
}

void EnterCREQ(Player::ptr& player, MatchRoom::ptr& matchRoom)
{
    for(auto tplayer : matchRoom->GetPlayers())
    {
        proto::EnterAndLeaveResponse enterResponse;
        enterResponse.set_iconname(tplayer->GetIconName().c_str());
        enterResponse.set_username(tplayer->GetName().c_str());
        enterResponse.set_seatposition(tplayer->GetSeatPosition());
        bool isPrepared = matchRoom->IsReady(tplayer->GetId());
        if(isPrepared == true)
        {
            enterResponse.set_isprepared(1001);
        }
        else
        {
            enterResponse.set_isprepared(1002);
        }
        int coin = DBManager::GetInstance()->GetCoin(tplayer->GetName());
        enterResponse.set_coin(coin);
        proto::MatchModel matchModel;
        matchModel.set_matchcode(proto::MatchCode::Enter_SRES);
        matchModel.set_msg(enterResponse.SerializeAsString().c_str());
        proto::NetMsg netMsg;
        netMsg.set_opcode(proto::OpCode::Match);
        netMsg.set_msg(matchModel.SerializeAsString().c_str());
        EnCodeTool::EnCode(netMsg, player->GetSocket()->GetSendBuf());
        player->GetSocket()->Send();
    }
}

void EnterBRO(Player::ptr& player, MatchRoom::ptr& matchRoom)
{
    //广播进入房间玩家的信息
    proto::EnterAndLeaveResponse enterResponse;
    enterResponse.set_iconname(player->GetIconName().c_str());
    enterResponse.set_username(player->GetName().c_str());
    enterResponse.set_seatposition(player->GetSeatPosition());
    enterResponse.set_isprepared(1002);
    int coin = DBManager::GetInstance()->GetCoin(player->GetName());
    enterResponse.set_coin(coin);
    proto::MatchModel matchModel;
    matchModel.set_matchcode(proto::MatchCode::Enter_SRES);
    matchModel.set_msg(enterResponse.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Match);
    netMsg.set_msg(matchModel.SerializeAsString().c_str());
    matchRoom->BroadCast(netMsg, false, player);
}

void LeaveMatchCREQ(Player::ptr& player, MatchRoom::ptr& matchRoom)
{
    proto::EnterAndLeaveResponse leaveRoomResponse;
    leaveRoomResponse.set_seatposition(player->GetSeatPosition());
    proto::MatchModel matchModel;
    matchModel.set_matchcode(proto::MatchCode::LeaveMatch_BRO);
    matchModel.set_msg(leaveRoomResponse.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Match);
    netMsg.set_msg(matchModel.SerializeAsString().c_str());
    matchRoom->BroadCast(netMsg, false, player);
}

void ReadyCREQ(Player::ptr& player, MatchRoom::ptr& matchRoom, proto::BOOL isReady)
{
    if(isReady == proto::BOOL::TRUE)
    {
        matchRoom->Ready(player->GetId());
    }
    else
    {
        matchRoom->CancelReady(player->GetId());
    }
    proto::ReadyResponse readyResponse;
    readyResponse.set_isready(isReady);
    readyResponse.set_seatposition(player->GetSeatPosition());
    proto::MatchModel matchModel;
    matchModel.set_matchcode(proto::MatchCode::Ready_BRO);
    matchModel.set_msg(readyResponse.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Match);
    netMsg.set_msg(matchModel.SerializeAsString().c_str());
    matchRoom->BroadCast(netMsg, false, player);
}

void StartGame(Player::ptr& player, MatchRoom::ptr& matchRoom)
{
    proto::MatchModel matchModel;
    matchModel.set_matchcode(proto::MatchCode::StartGame_BRO);
    matchRoom->PickBanker();
    matchRoom->DealCard();
    matchRoom->SortCard();
    matchRoom->GetCardType();
    auto it = matchRoom->GetPlayers().begin();
    while(it != matchRoom->GetPlayers().end())
    {
        for(int i = 0; i < 3; i++)
        {
            proto::StartFightResponse startFightResponse;
            startFightResponse.set_cardname((*it)->GetCards()[i]->GetCardName());
            proto::FightModel fightModel;
            fightModel.set_fightcode(proto::FightCode::StartFight_BRO);
            fightModel.set_msg(startFightResponse.SerializeAsString().c_str());
            proto::NetMsg netMsg;
            netMsg.set_opcode(proto::OpCode::Fight);
            netMsg.set_msg(matchModel.SerializeAsString().c_str());
            EnCodeTool::EnCode(netMsg, (*it)->GetSocket()->GetSendBuf());
            (*it)->GetSocket()->Send();
        }
        it++;
    }
    proto::Banker banker;
    Player::ptr bplayer = matchRoom->GetBanker();
    banker.set_seatposition(bplayer->GetSeatPosition());
    proto::FightModel fightModel;
    fightModel.set_fightcode(proto::FightCode::Banker_SRES);
    fightModel.set_msg(banker.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Fight);
    netMsg.set_msg(matchModel.SerializeAsString().c_str());
    EnCodeTool::EnCode(netMsg, bplayer->GetSocket()->GetSendBuf());
    bplayer->GetSocket()->Send();
}

void MatchHandler::Process(Player::ptr& player)
{
    switch (m_matchModel.matchcode())
    {
    case proto::MatchCode::Enter_CREQ :
        {
            proto::EnterRequest enterRequest;
            enterRequest.ParseFromArray(m_matchModel.msg().c_str(), m_matchModel.msg().size());
            MatchRoom::ptr room = RoomMgr::GetInstance()->Enter(player, enterRequest.roomtype());
            EnterCREQ(player, room);
            EnterBRO(player, room);
        }
        break;
    case proto::MatchCode::LeaveMatch_CREQ :
        {
            MatchRoom::ptr room = RoomMgr::GetInstance()->Leave(player);
            LeaveMatchCREQ(player, room);
        }
        break;
    case proto::MatchCode::Ready_CREQ :
        {
            proto::ReadyRequest readyRequest;
            readyRequest.ParseFromArray(m_matchModel.msg().c_str(), m_matchModel.msg().size());
            MatchRoom::ptr room = RoomMgr::GetInstance()->GetRoom(player);
            ReadyCREQ(player, room, readyRequest.isready());
            if(room->IsAllReady())
            {
                StartGame(player, room);
            }
        }
    default:
        break;
    }
}

